package my.websocket.download;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import my.websocket.util.ThreadUtils;

import javax.net.ssl.SSLException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class Download {

    public static void download(String url, EventLoopGroup workerGroup) throws InterruptedException, URISyntaxException, IOException {
        URI uri = new URI(url);
        String scheme = uri.getScheme() == null ? "http" : uri.getScheme();
        String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
        int port = uri.getPort();
        String fileName = url.substring(url.lastIndexOf('/') + 1);
        if (port == -1) {
            if ("http".equalsIgnoreCase(scheme)) {
                port = 80;
            } else if ("https".equalsIgnoreCase(scheme)) {
                port = 443;
            }
        }
        final boolean ssl = "https".equalsIgnoreCase(scheme);

        File file = new File("d://" + fileName + ".log");
        String start = "0";
        if (file.exists()) {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            start = reader.readLine();
        }

        Bootstrap bootstrap = new Bootstrap();
        Channel channel = bootstrap.group(workerGroup).channel(NioSocketChannel.class)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws SSLException {
                        ChannelPipeline pipeline = ch.pipeline();
                        if (ssl) {
                            pipeline.addLast(SslContextBuilder.forClient()
                                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                                    .build().newHandler(ch.alloc()));
                        }
                        pipeline.addLast(new HttpClientCodec(4096, 8192, 81920));
                        pipeline.addLast(new HttpContentDecompressor());
                        pipeline.addLast(ThreadUtils.BLOCK_EVENT_LOOP_GROUP,
                                new DownloadTaskHandler("d://" + fileName));
                    }
                }).connect(host, port).sync().channel();

        HttpRequest request = new DefaultFullHttpRequest(
                HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath(), Unpooled.EMPTY_BUFFER);
        request.headers().set(HttpHeaderNames.HOST, host);
        request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
        request.headers().set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP);
        request.headers().set(HttpHeaderNames.RANGE, "bytes=" + start + "-");

        channel.writeAndFlush(request);
        channel.closeFuture().sync();
    }
}
